﻿////////////////////////////////////////////////////////////////
///
/// File: Emitter.cs
/// Author: Lucio Davide Spano
/// Last update: 27 July 2012
/// Description: This class represent the protocol for fowarding
///              low-level device events to the gesture expression
/// To do: 
/// ------------------------------------------------------------
/// Copyright (c) 2012 Lucio Davide Spano 
///                     (lucio.davide.spano@isti.cnr.it)
/// 
/// The use and distribution terms for this software are 
/// contained in the file named license.txt, which can be found 
/// in the root of this distribution.
/// By using this software in any fashion, you are agreeing to 
/// be bound by the terms of this license.
///
/// You must not remove this notice, or any other, from this
/// software.
/// ------------------------------------------------------------
////////////////////////////////////////////////////////////////

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GestIT
{
    public class Emitter
    {
        protected TmpExp gesture;
        protected List<SimpleTmpExp> leafs;
        protected List<bool> flags;
        protected long time;

        public Emitter()
        {
            gesture = null;
            leafs = new List<SimpleTmpExp>();
            flags = new List<bool>();
        }

        public void SetGestureDescription(TmpExp gesture)
        {
            leafs.Clear();
            flags.Clear();
            this.gesture = gesture;
            CreateLeafList(gesture);
        }

        public void FeedDeviceEvent(ExpEventArgs args)
        {
            for (int i = 0; i < leafs.Count; i++)
            {
                if (leafs[i].State == ExecState.Enabled)
                {
                    flags[i] = true;
                }
            }

            bool executed = false;

            for (int i = 0; i < leafs.Count; i++)
            {
                if (flags[i] && leafs[i] != null)
                {
                    if (!leafs[i].Accepts(args))
                    {
                        leafs[i].NotAccepted(args);
                        flags[i] = false;
                    }
                }
            }

            for (int i = 0; i < leafs.Count; i++)
            {
                if (flags[i] && leafs[i] != null)
                {
                    leafs[i].Consume(args);
                    executed = true;
                }
            }

            if (!executed)
            {
                foreach (SimpleTmpExp s in leafs)
                {
                    if (s.State != ExecState.Disabled)
                    {
                        Console.WriteLine("Invalidate");
                        s.Invalidate(args);
                    }
                }
            }

            time++;
        }

        public void StartRecognition(Token token)
        {
            if (gesture != null)
            {
                time = 0;
                gesture.SetExectState(ExecState.Disabled, token);
                gesture.SetExectState(ExecState.Enabled, token);
            }
        }

        private void CreateLeafList(TmpExp exp)
        {
            if (exp == null)
            {
                return;
            }
            switch (exp.Type)
            {
                case ExpType.Simple:
                    SimpleTmpExp simple = (SimpleTmpExp)exp;
                    this.leafs.Add(simple);
                    this.flags.Add(false);
                    break;

                case ExpType.Binary:
                    BinaryTmpExp binary = (BinaryTmpExp)exp;
                    this.CreateLeafList(binary.LeftOperand);
                    this.CreateLeafList(binary.RightOperand);
                    break;

                case ExpType.Complex:
                    ComplexTmpExp complex = (ComplexTmpExp)exp;
                    foreach (TmpExp op in complex.GetOperands())
                    {
                        CreateLeafList(op);
                    }
                    break;
            }
        }
    }
}
